from typing import Dict, Any, List, Optional
from fastapi import FastAPI, Response
import uvicorn
import threading

from motor.engine_server.config.base import ServerConfig
from motor.engine_server.core.service import Service
from motor.engine_server.utils.logger import run_log


class Endpoint:
    def __init__(self, server_config: ServerConfig, services: List[Service] = None):
        self.host = server_config.server_host
        self.port = server_config.server_port
        self.metrics_service = services[0]
        self.health_service = services[1]
        self.app = FastAPI(title="EngineServer Endpoint")
        self._stop_event = threading.Event()
        self._server: Optional[uvicorn.Server] = None
        self._server_thread = threading.Thread(
            target=self._run_server,
            name="endpoint_server_thread",
            daemon=True
        )

        self._register_routes()

    def _register_routes(self):
        @self.app.get("/status")
        def get_status(response: Response) -> Dict[str, Any]:
            response.status_code = 200
            server_core_status = "init"
            collect_status = "init"
            if self.health_service:
                health_data = self.health_service.get_data()
                server_core_status = health_data.get("latest_health", {}).get("core_status", "init")
                collect_status = health_data.get("latest_health", {}).get("status", "init")
            if server_core_status == "init":
                run_log.info("Server core is initializing.")
                return {
                    "status": "init"
                }
            if collect_status == "failed" or server_core_status == "abnormal":
                return {
                    "status": "abnormal"
                }
            return {
                "status": "normal"
            }

        @self.app.get("/metrics")
        def get_metrics(response: Response):
            metrics_data = {}
            server_core_status = "init"
            collect_status = "init"
            if self.metrics_service:
                metrics_data = self.metrics_service.get_data()
                server_core_status = metrics_data.get("latest_metrics", {}).get("core_status", "init")
                collect_status = metrics_data.get("latest_metrics", {}).get("status", "init")

            if server_core_status == "init":
                run_log.info("Server core is initializing.")
                return Response(
                    content="",
                    media_type="text/plain",
                    status_code=200
                )
            if collect_status == "success":
                response_data = metrics_data.get("latest_metrics", {}).get("data")
                return Response(
                    content=response_data,
                    media_type="text/plain",
                    status_code=200
                )
            return Response(
                content="",
                media_type="text/plain",
                status_code=200
            )

    def run(self):
        if not self._server_thread or not self._server_thread.is_alive():
            self._server_thread.start()
            run_log.info(f"Endpoint server started: http://{self.host}:{self.port}")

    def _run_server(self):
        config = uvicorn.Config(
            app=self.app,
            host=self.host,
            port=self.port,
            log_level="warning",
            workers=1
        )
        self._server = uvicorn.Server(config)
        if not self._stop_event.is_set():
            self._server.run()

    def shutdown(self):
        if self._server:
            self._server.should_exit = True
            run_log.info("Endpoint: Uvicorn server exit triggered")
        self._stop_event.set()
        if self._server_thread and self._server_thread.is_alive():
            self._server_thread.join(timeout=5)
            log_msg = "exited" if not self._server_thread.is_alive() else "timeout"
            run_log.info(f"Endpoint server thread {log_msg}")
        run_log.info("Endpoint server stopped completely")
